package com.onpositive.mediawiki.propertyparser;

import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.StringTokenizer;

import com.onpositive.data.units.DateWithAccuracy;
import com.onpositive.semantic.model.api.meta.IMeta;
import com.onpositive.units.AbstractPreprocessor;
import com.onpositive.units.AbstractValueParser;
import com.onpositive.units.ParsedDate;
import com.onpositive.units.ParsedIdent;
import com.onpositive.units.ParsedScalar;
import com.onpositive.units.ParsedString;
import com.onpositive.units.ParsedValue;
import com.onpositive.units.UndefinedParsedValue;

public class UnitParser extends AbstractValueParser {
	
	static private DimensionParser dimensionParser = new DimensionParser() ;
	
	public static ParsedValue parseStatically(String value, IMeta meta, String comment) {
		
		StringTokenizer ts = new StringTokenizer(value, " ");
		String nextToken = ts.nextToken();

		DateFormat dateInstance = new SimpleDateFormat("dd MM yyyy", Locale.US );
		try {
			Date parse = dateInstance.parse(value);
			
			return new ParsedDate(parse, DateWithAccuracy.ACCURACY_DAY, getDefaultComment());
		} catch (Exception e) {
			dateInstance = new SimpleDateFormat("dd MMMM yyyy", Locale.US );
			try {
				Date parse = dateInstance.parse(value);
				return new ParsedDate(parse, DateWithAccuracy.ACCURACY_DAY, getDefaultComment());
			} catch (ParseException e1) {				
			}
			dateInstance = new SimpleDateFormat("MMMM yyyy", Locale.US );
			try {
				Date parse = dateInstance.parse(value);
				return new ParsedDate(parse, DateWithAccuracy.ACCURACY_MONTH, getDefaultComment());
			} catch (ParseException e1) {
				dateInstance = new SimpleDateFormat("yyyy MMMM", Locale.US );
				try {
					Date parse = dateInstance.parse(value);
					return new ParsedDate(parse, DateWithAccuracy.ACCURACY_MONTH, getDefaultComment());
				} catch (ParseException e2) {
				}
			}
			// TODO: handle exception
		}

		double doubleValue = 0.0;
		try {
			doubleValue = NumberFormat.getInstance(Locale.US).parse(nextToken).doubleValue();
						
			if (ts.hasMoreTokens()) {
				
				String dimension = ts.nextToken();
				
				String val = nextToken + " " + dimension ;
				ParsedValue pv = dimensionParser.parse(val, meta, comment ) ;
				if( pv != null )
					return pv ;
				else
					throw new ParseException( "", 0) ;
				//System.out.println(dimension);
			} else {
				String vl=value.trim();
				for (int a=0;a<vl.length();a++){
					char charAt = vl.charAt(a);
					if (!Character.isDigit(charAt)&&charAt!='.'&&charAt!=','&&charAt!=' '){
						return new UndefinedParsedValue( value, getDefaultComment() );
					}
				}
				return new ParsedScalar(doubleValue, getDefaultComment());
			}
		} catch (ParseException e) {
			String vl=value.trim();
			boolean isIndent=true ;
			for (int a=0;a<vl.length();a++){
				if (!Character.isJavaIdentifierPart(vl.charAt(a))){
					isIndent = false;
					break ;
				}
			}
			if (isIndent)
				return new ParsedIdent(vl, getDefaultComment());
		}
		
		return new ParsedString( value, getDefaultComment() );
	}

	private static String getDefaultComment(){
		
		return UnitParser.class.getSimpleName() ;
	}

	@Override
	public AbstractPreprocessor getPreprocessor() {		
		return null;
	}

	@Override
	public ParsedValue parse(String s, IMeta meta, String comment) {
		return parseStatically( s, meta, comment) ;
	}
}
